package com.example.app;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.Log;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadUtil {
    static final String TAG = ThreadUtil.class.getSimpleName();
    static int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    static int CORE_POOL_SIZE = CPU_COUNT + 1;
    static int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;// IO 密集型，为了等待 IO
    static int MAXIMUM_POOL_SIZE_ = CPU_COUNT + 1;// CPU 密集型
    static int KEEP_ALIVE = 1;
    static ThreadFactory THREAD_FACTORY = new ThreadFactory() {
        private final AtomicInteger count = new AtomicInteger(1);
        public Thread newThread(Runnable r) {
            return new Thread(r, "ScheduledExecutor-" + count.getAndIncrement());
        }
    };
    static BlockingQueue<Runnable> WORK_QUEUE = new LinkedBlockingQueue<>(128);
    static ScheduledThreadPoolExecutor SCHEDULED_POOL_EXECUTOR = new ScheduledThreadPoolExecutor(CORE_POOL_SIZE,
            THREAD_FACTORY);
    static ExecutorService POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE,
            MAXIMUM_POOL_SIZE,
            KEEP_ALIVE,
            TimeUnit.SECONDS,
            WORK_QUEUE,
            THREAD_FACTORY);

    public static void execute(Runnable r) {
        Log.i(TAG, "execute: " + r);
        POOL_EXECUTOR.execute(r);
    }

    public static ScheduledFuture<?> scheduleAtFixedRate(Runnable r, long initialDelay, long period) {
        Log.i(TAG, "scheduleAtFixedRate: " + r + "/" + initialDelay + "/" + period);
        return SCHEDULED_POOL_EXECUTOR.scheduleAtFixedRate(r,
                initialDelay, period, TimeUnit.MILLISECONDS);
    }

    public static ScheduledFuture<?> scheduleWithFixedDelay(Runnable r, long initialDelay, long delay) {
        Log.i(TAG, "scheduleAtFixedRate: " + r + "/" + initialDelay + "/" + delay);
        return SCHEDULED_POOL_EXECUTOR.scheduleWithFixedDelay(r,
                initialDelay, delay, TimeUnit.MILLISECONDS);
    }

    public static void remove(Runnable r) {
        Log.i(TAG, "remove: " + r);
        SCHEDULED_POOL_EXECUTOR.remove(r);
    }
    static Looper LOOPER;
    static Handler HANDLER;

    public static Looper getLooper() {
        if (LOOPER == null) {
            HandlerThread thread = new HandlerThread("HandlerThread-UI");
            thread.start();
            LOOPER = thread.getLooper();
        }
        return LOOPER;
    }

    public static Handler getHandler() {
        if (HANDLER == null) {
            HANDLER = new Handler(getLooper());
        }
        return HANDLER;
    }
}
